package name.luojun.DBhelper;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import name.luojun.DBhelper.TableManager;
import name.luojun.DBhelper.iface.IUpgrade;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.hibernate.EntityMode;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class HibernateUpgradeSupport extends HibernateDaoSupport implements IUpgrade {
	private String hql;
	private String filePath;
	private String rule;
	@Override
	protected void initDao() throws Exception {
		super.initDao();
		if (hql == null || hql.length() == 0) {
			throw new RuntimeException("hql should not be null");
		}
		if (filePath == null || filePath.length() == 0) {
			throw new RuntimeException("filePath should not be null");
		}
		doUpgrade();
	}
	@SuppressWarnings("rawtypes")
	public void dataExport() {
		Document doc = DocumentHelper.createDocument();
		Element root = doc.addElement("root");
		Session session = getXmlSession();
		List results = this.getAll(session);
		addResultsToNode(results, root);
		OutputFormat format = OutputFormat.createPrettyPrint();
		try {
			XMLWriter writer = new XMLWriter(new FileWriter(filePath), format);
			writer.write(doc);
			writer.close();
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		}
	}
	public List getAll(Session session) {
		List results = session.createQuery("from " + hql).list();
		return results;
	}
	@SuppressWarnings("rawtypes")
	public void dataImport() {
		Session session = getXmlSession();
		Transaction txn = session.beginTransaction();
		try {
			if (this.getRule().equalsIgnoreCase(UpgradeManager.COVER)) {
				List before = getAll(session);
				for (Object o : before) {
					session.delete(o);
				}
				session.flush();
			}
			SAXReader reader = new SAXReader();
			Document doc = reader.read(new File(filePath));
			List elems = doc.getRootElement().elements();
			Iterator it = elems.iterator();
			ReplicationMode mode = ReplicationMode.IGNORE;
			if (this.getRule().equalsIgnoreCase(UpgradeManager.ADD))
				mode = ReplicationMode.IGNORE;
			else if (this.getRule().equalsIgnoreCase(UpgradeManager.INSERTORUPDATE))
				mode = ReplicationMode.OVERWRITE;
			while (it.hasNext()) {
				Element e = (Element) it.next();
				if (e.getName().equals(hql)) {
					session.replicate(hql, e, mode);
				}
			}
			txn.commit();
			session.close();
		} catch (Exception e) {
			txn.rollback();
			throw new RuntimeException(e);
		}
	}
	private Session getXmlSession() {
		return this.getSessionFactory().openSession().getSession(EntityMode.DOM4J);
	}
	@SuppressWarnings("rawtypes")
	private void addResultsToNode(List results, Element root) {
		for (Iterator i = results.iterator(); i.hasNext();) {
			Element e = (Element) i.next();
			e.setName(hql);
			if (e != null) {
				root.add(e);
			}
		}
	}
	public void deleteFile() {
		File file = new File(filePath);
		if (file.exists())
			file.delete();
	}
	public String getHql() {
		return hql;
	}
	public void setHql(String hql) {
		this.hql = hql;
	}
	public String getFilePath() {
		return filePath;
	}
	public void setFilePath(String filePath) {
		this.filePath = TableManager.cleanPath(filePath);
	}
	@Override
	public void createBackFile() {
		dataExport();
	}
	public String getRule() {
		return rule != null ? rule : UpgradeManager.INSERTORUPDATE;
	}
	public void setRule(String rule) {
		this.rule = rule;
	}
	@Override
	public void doUpgrade() {
		File file = new File(filePath);
		if (!file.exists()) {
			this.logger.error("file not exist," + hql + " upgrade stoped,path:" + filePath);
			return;
		}
		dataImport();
		deleteFile();
	}
}
